﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProgramacionRedes {
    public class Usuario {
        public string Nombre { get; set; }
        public string Mail { get; set; }
        public int Id { get; set; }
        public string Password { get; set; }
        public int CantVecesConectado { get; set; }
        public List<Usuario> Amigos { get; set; }
        public List<Usuario> AmigosBloqueados { get; set; }
        public List<Usuario> AmigosNoBloqueados { get; set; }
        public List<Estado> Estados { get; set; }

        private int indiceEstado;

        public Usuario() {
            indiceEstado = 0;
            Amigos = new List<Usuario>();
            AmigosBloqueados = new List<Usuario>();
            AmigosNoBloqueados = new List<Usuario>();
            Estados = new List<Estado>();
        }

        public Usuario(string nombre, string password, int id, string mail) {
            Nombre = nombre;
            Password = password;
            Id = id;
            Mail = mail;
            indiceEstado = 0;
            Amigos = new List<Usuario>();
            AmigosBloqueados = new List<Usuario>();
            AmigosNoBloqueados = new List<Usuario>();
            Estados = new List<Estado>();
        }

        public bool AgregarAmigo(Usuario usuario) {
            if (!Amigos.Contains(usuario)) {
                Amigos.Add(usuario);
                AmigosNoBloqueados.Add(usuario);
                usuario.AgregarAmigo(this);
                return true;
            } else {
                return false;
            }
        }

        public bool BloquearAmigo(Usuario usuario) {
            if (Amigos.Contains(usuario)) {
                if (AmigosNoBloqueados.Contains(usuario)) {
                    AmigosNoBloqueados.Remove(usuario);
                    AmigosBloqueados.Add(usuario);
                }
                return true;
            } else {
                return false;
            }
        }

        public bool DesbloquearAmigo(Usuario usuario) {
            if (Amigos.Contains(usuario)) {
                if (AmigosBloqueados.Contains(usuario)) {
                    AmigosBloqueados.Remove(usuario);
                    AmigosNoBloqueados.Add(usuario);
                }
                return true;
            } else {
                return false;
            }
        }

        public bool QuitarAmigo(Usuario usuario) {
            if (Amigos.Contains(usuario)) {
                Amigos.Remove(usuario);
                if (AmigosNoBloqueados.Contains(usuario)) {
                    AmigosNoBloqueados.Remove(usuario);
                } else {
                    AmigosBloqueados.Remove(usuario);
                }
                return true;
            } else {
                return false;
            }
        }

        public bool AgregarEstado(string estado) {
            Estados.Add(new Estado(ObtenerAutoIncrementado(), estado));
            return true;
        }

        private int ObtenerAutoIncrementado() {
            indiceEstado++;
            return indiceEstado;
        }

        public List<Estado> ObtenerEstados(Usuario usuario) {
            if (usuario == this) {
                return Estados;
            } else {
                if (Amigos.Contains(usuario)) {
                    return usuario.ObtenerEstados(usuario);
                } else {
                    throw new Exception("No se puede obtener los estados de un usuario del cual no se es amigo");
                }
            }
        }

        public void ComentarEstado(Usuario usuario_que_comenta, int idEstado, string texto) {
            if (usuario_que_comenta == this) {
                Estado estado = ObtenerEstado(idEstado);
                estado.Comentar(usuario_que_comenta, texto);
            } else {
                if (Amigos.Contains(usuario_que_comenta)) {
                    if (AmigosNoBloqueados.Contains(usuario_que_comenta)) {
                        usuario_que_comenta.RecibirComentarEstado(this, idEstado, texto);
                    } else {
                        throw new Exception("El usuario está bloqueado");
                    }
                } else {
                    throw new Exception("No se puede comentar el estado de un usuario que no es amigo");
                }

            }
        }

        private void RecibirComentarEstado(Usuario usuario, int idEstado, string texto) {
            if (Amigos.Contains(usuario)) {
                if (AmigosNoBloqueados.Contains(usuario)) {
                    Estado estado = ObtenerEstado(idEstado);
                    estado.Comentar(usuario, texto);
                } else {
                    throw new Exception("El usuario está bloqueado");
                }
            } else {
                throw new Exception("El usuario que comenta no es amigo del usuario que recibe el comentario");
            }
        }

        private Estado ObtenerEstado(int idEstado) {
            foreach (Estado e in Estados) {
                if (e.Id == idEstado) return e;
            }
            throw new Exception("No existe estado");
        }

        public override bool Equals(object obj) {
            return ((Usuario)obj).Nombre.Equals(Nombre);
        }

        public void QuitarEstado(int id_estado) {
            foreach (Estado e in Estados) {
                if (e.Id == id_estado) {
                    Estados.Remove(e);
                }
            }
            throw new Exception("No existe estado con ese id");
        }
    }
}
